#pragma once 
#include<iostream>
#include<string.h>
using namespace std;

namespace bit
{
  class string 
  {
  public:
    typedef char* iterator;
    typedef const char* const_iterator;
    iterator begin()
		{
			return _str;
		}
    iterator end()
    {
      return _str+_size;
    }
    string(const char* str)
      :_size(strlen(str))
      ,_capacity(_size)
      ,_str(new char[_capacity + 1])
    {
      strcpy(_str,str);
    }
    
    const_iterator begin() const
		{
			return _str;
		}

    const_iterator end() const 
    {
      return _str + _size;
    }

    string(const string& s)
    {
        _str = new char[s._capacity + 1];
        strcpy(_str,s._str);
        _size = s._size;
        _capacity = s._capacity;
    }

    const char* c_str() const 
    {
      return _str;
    }
    
    size_t size() const 
    {
      return _size;
    }
    
    char& operator[](size_t pos)
    {
      assert(pos<_size);

      return _str[pos];
    }

    const char& operator[](size_t pos) const 
    {
      assert(pos < _size);
      return _str[pos];
    }
    
    void reserve(size_t n)
    {
      if(n > _capacity)
      {
        char* tmp = new char[n+1];
        strcpy(tmp,_str);
        delete[] _str;
        _str = tmp;
        _capacity = n;
      }
    }

    void push_back(char ch)
    {
      if(_size == _capacity)
      {
        reserve(_capacity == 0 ? 4 : _capacity * 2);
      }
      _str[_size] = ch;
      ++_size;
      _str[_size] = '\0';
    }

    void append(const char* str)
    {
      int len = strlen(_str);
      if(_size + len > _capacity)
      {
        reserve(_size + len);
      }
      strcpy(_str+_size,str);
      _size += len;
    }
    
    string& operator+=(char ch)
    {
      push_back(ch);
      return *this;
    }

    string& operator+=(const char* str)
    {
      append(str);
      return *this;
    }

    void insert(size_t pos, size_t n, char ch)
    {
      assert(pos <= _size && pos >= 0);
      if (_size +n > _capacity)
      {
        reserve(_size + n);
      }

      // 挪动数据
			int end = _size;
			while (end >= (int)pos)
			{
				_str[end + n] = _str[end];
				--end;
			}
      for (size_t i = 0; i < n; i++)
			{
				_str[pos + i] = ch;
			}
      _size += n;
    }
    
    void erase(size_t pos, size_t len = npos)
    {
      assert(pos <= _size);
      if (len == npos || pos + len >= _size)
			{
				_str[pos] = '\0';
				_size = pos;

				_str[_size] = '\0';
			} 
      else
			{
				size_t end = pos + len;
				while (end <= _size)
				{
					_str[pos++] = _str[end++];
				}
				_size -= len;
			}

    }
    
    size_t find(const char* str , size_t pos = 0)
		{
			assert(pos < _size);

			const char* ptr = strstr(_str + pos, str);
			if (ptr)
			{
				return ptr - _str;
			}
			else
			{
				return npos;
			}
		}

		string substr(size_t pos = 0, size_t len = npos)
		{
			assert(pos < _size);

			size_t n = len;
			if (len == npos || pos + len > _size)
			{
				n = _size - pos;
			}

			string tmp;
			tmp.reserve(n);
			for (size_t i = pos; i < pos + n; i++)
			{
				tmp += _str[i];
			}

			return tmp;
		}


    ~string()
    {
      delete[] _str;
      _str = NULL;
      _size = _capacity = 0;
    }
    


    void Print()
    { 
      cout<<_str<<endl;
    }
  private:
     unsigned int  _size;
     unsigned int  _capacity;
     char* _str;
  };
};


